package roaring
import (
"fmt"
"sort"
"unsafe"
)
type runContainer16 struct {
iv []interval16
}
type interval16 struct {
start uint16
length uint16
}
func newInterval16Range(start , last uint16 ) interval16 {
if last < start {
panic (fmt .Sprintf ("last (%d) cannot be smaller than start (%d)" , last , start ))
}
return interval16 {
start ,
last - start ,
}
}
func (iv interval16 ) runlen () int {
return int (iv .length ) + 1
}
func (iv interval16 ) last () uint16 {
return iv .start + iv .length
}
func (iv interval16 ) String () string {
return fmt .Sprintf ("[%d, %d]" , iv .start , iv .length )
}
func ivalString16(iv []interval16 ) string {
var s string
var j int
var p interval16
for j , p = range iv {
s += fmt .Sprintf ("%v:[%d, %d], " , j , p .start , p .last ())
}
return s
}
func (rc *runContainer16 ) String () string {
if len (rc .iv ) == 0 {
return "runContainer16{}"
}
is := ivalString16 (rc .iv )
return `runContainer16{` + is + `}`
}
type uint16Slice []uint16
func (p uint16Slice ) Len () int { return len (p ) }
func (p uint16Slice ) Less (i , j int ) bool { return p [i ] < p [j ] }
func (p uint16Slice ) Swap (i , j int ) { p [i ], p [j ] = p [j ], p [i ] }
type addHelper16 struct {
runstart uint16
runlen uint16
actuallyAdded uint16
m []interval16
rc *runContainer16
}
func (ah *addHelper16 ) storeIval (runstart , runlen uint16 ) {
mi := interval16 {start : runstart , length : runlen }
ah .m = append (ah .m , mi )
}
func (ah *addHelper16 ) add (cur , prev uint16 , i int ) {
if cur == prev +1 {
ah .runlen ++
ah .actuallyAdded ++
} else {
if cur < prev {
panic (fmt .Sprintf ("newRunContainer16FromVals sees " +
"unsorted vals; vals[%v]=cur=%v < prev=%v. Sort your vals" +
" before calling us with alreadySorted == true." , i , cur , prev ))
}
if cur == prev {
} else {
ah .actuallyAdded ++
ah .storeIval (ah .runstart , ah .runlen )
ah .runstart = cur
ah .runlen = 0
}
}
}
func newRunContainer16Range(rangestart uint16 , rangelast uint16 ) *runContainer16 {
rc := &runContainer16 {}
rc .iv = append (rc .iv , newInterval16Range (rangestart , rangelast ))
return rc
}
func newRunContainer16FromVals(alreadySorted bool , vals ...uint16 ) *runContainer16 {
rc := &runContainer16 {}
ah := addHelper16 {rc : rc }
if !alreadySorted {
sort .Sort (uint16Slice (vals ))
}
n := len (vals )
var cur , prev uint16
switch {
case n == 0 :
case n == 1 :
ah .m = append (ah .m , newInterval16Range (vals [0 ], vals [0 ]))
ah .actuallyAdded ++
default :
ah .runstart = vals [0 ]
ah .actuallyAdded ++
for i := 1 ; i < n ; i ++ {
prev = vals [i -1 ]
cur = vals [i ]
ah .add (cur , prev , i )
}
ah .storeIval (ah .runstart , ah .runlen )
}
rc .iv = ah .m
return rc
}
func newRunContainer16FromBitmapContainer(bc *bitmapContainer ) *runContainer16 {
rc := &runContainer16 {}
nbrRuns := bc .numberOfRuns ()
if nbrRuns == 0 {
return rc
}
rc .iv = make ([]interval16 , nbrRuns )
longCtr := 0
curWord := bc .bitmap [0 ]
runCount := 0
for {
for curWord == 0 && longCtr < len (bc .bitmap )-1 {
longCtr ++
curWord = bc .bitmap [longCtr ]
}
if curWord == 0 {
return rc
}
localRunStart := countTrailingZeros (curWord )
runStart := localRunStart + 64 *longCtr
curWordWith1s := curWord | (curWord - 1 )
runEnd := 0
for curWordWith1s == maxWord && longCtr < len (bc .bitmap )-1 {
longCtr ++
curWordWith1s = bc .bitmap [longCtr ]
}
if curWordWith1s == maxWord {
runEnd = wordSizeInBits + longCtr *64
rc .iv [runCount ].start = uint16 (runStart )
rc .iv [runCount ].length = uint16 (runEnd ) - uint16 (runStart ) - 1
return rc
}
localRunEnd := countTrailingZeros (^curWordWith1s )
runEnd = localRunEnd + longCtr *64
rc .iv [runCount ].start = uint16 (runStart )
rc .iv [runCount ].length = uint16 (runEnd ) - 1 - uint16 (runStart )
runCount ++
curWord = curWordWith1s & (curWordWith1s + 1 )
}
}
func newRunContainer16FromArray(arr *arrayContainer ) *runContainer16 {
rc := &runContainer16 {}
ah := addHelper16 {rc : rc }
n := arr .getCardinality ()
var cur , prev uint16
switch {
case n == 0 :
case n == 1 :
ah .m = append (ah .m , newInterval16Range (arr .content [0 ], arr .content [0 ]))
ah .actuallyAdded ++
default :
ah .runstart = arr .content [0 ]
ah .actuallyAdded ++
for i := 1 ; i < n ; i ++ {
prev = arr .content [i -1 ]
cur = arr .content [i ]
ah .add (cur , prev , i )
}
ah .storeIval (ah .runstart , ah .runlen )
}
rc .iv = ah .m
return rc
}
func (rc *runContainer16 ) set (alreadySorted bool , vals ...uint16 ) {
rc2 := newRunContainer16FromVals (alreadySorted , vals ...)
un := rc .union (rc2 )
rc .iv = un .iv
}
func canMerge16(a , b interval16 ) bool {
if int (a .last ())+1 < int (b .start ) {
return false
}
return int (b .last ())+1 >= int (a .start )
}
func haveOverlap16(a , b interval16 ) bool {
if int (a .last ())+1 <= int (b .start ) {
return false
}
return int (b .last ())+1 > int (a .start )
}
func mergeInterval16s(a , b interval16 ) (res interval16 ) {
if !canMerge16 (a , b ) {
panic (fmt .Sprintf ("cannot merge %#v and %#v" , a , b ))
}
if b .start < a .start {
res .start = b .start
} else {
res .start = a .start
}
if b .last () > a .last () {
res .length = b .last () - res .start
} else {
res .length = a .last () - res .start
}
return
}
func intersectInterval16s(a , b interval16 ) (res interval16 , isEmpty bool ) {
if !haveOverlap16 (a , b ) {
isEmpty = true
return
}
if b .start > a .start {
res .start = b .start
} else {
res .start = a .start
}
bEnd := b .last ()
aEnd := a .last ()
var resEnd uint16
if bEnd < aEnd {
resEnd = bEnd
} else {
resEnd = aEnd
}
res .length = resEnd - res .start
return
}
func (rc *runContainer16 ) union (b *runContainer16 ) *runContainer16 {
var m []interval16
alim := int (len (rc .iv ))
blim := int (len (b .iv ))
var na int
var nb int
var merged interval16
var mergedUsed bool
var cura interval16
var curb interval16
pass := 0
for na < alim && nb < blim {
pass ++
cura = rc .iv [na ]
curb = b .iv [nb ]
if mergedUsed {
mergedUpdated := false
if canMerge16 (cura , merged ) {
merged = mergeInterval16s (cura , merged )
na = rc .indexOfIntervalAtOrAfter (int (merged .last ())+1 , na +1 )
mergedUpdated = true
}
if canMerge16 (curb , merged ) {
merged = mergeInterval16s (curb , merged )
nb = b .indexOfIntervalAtOrAfter (int (merged .last ())+1 , nb +1 )
mergedUpdated = true
}
if !mergedUpdated {
m = append (m , merged )
mergedUsed = false
}
continue
} else {
if !canMerge16 (cura , curb ) {
if cura .start < curb .start {
m = append (m , cura )
na ++
} else {
m = append (m , curb )
nb ++
}
} else {
merged = mergeInterval16s (cura , curb )
mergedUsed = true
na = rc .indexOfIntervalAtOrAfter (int (merged .last ())+1 , na +1 )
nb = b .indexOfIntervalAtOrAfter (int (merged .last ())+1 , nb +1 )
}
}
}
var aDone , bDone bool
if na >= alim {
aDone = true
}
if nb >= blim {
bDone = true
}
if mergedUsed {
if !aDone {
aAdds :
for na < alim {
cura = rc .iv [na ]
if canMerge16 (cura , merged ) {
merged = mergeInterval16s (cura , merged )
na = rc .indexOfIntervalAtOrAfter (int (merged .last ())+1 , na +1 )
} else {
break aAdds
}
}
}
if !bDone {
bAdds :
for nb < blim {
curb = b .iv [nb ]
if canMerge16 (curb , merged ) {
merged = mergeInterval16s (curb , merged )
nb = b .indexOfIntervalAtOrAfter (int (merged .last ())+1 , nb +1 )
} else {
break bAdds
}
}
}
m = append (m , merged )
}
if na < alim {
m = append (m , rc .iv [na :]...)
}
if nb < blim {
m = append (m , b .iv [nb :]...)
}
res := &runContainer16 {iv : m }
return res
}
func (rc *runContainer16 ) unionCardinality (b *runContainer16 ) uint {
answer := uint (0 )
alim := int (len (rc .iv ))
blim := int (len (b .iv ))
var na int
var nb int
var merged interval16
var mergedUsed bool
var cura interval16
var curb interval16
pass := 0
for na < alim && nb < blim {
pass ++
cura = rc .iv [na ]
curb = b .iv [nb ]
if mergedUsed {
mergedUpdated := false
if canMerge16 (cura , merged ) {
merged = mergeInterval16s (cura , merged )
na = rc .indexOfIntervalAtOrAfter (int (merged .last ())+1 , na +1 )
mergedUpdated = true
}
if canMerge16 (curb , merged ) {
merged = mergeInterval16s (curb , merged )
nb = b .indexOfIntervalAtOrAfter (int (merged .last ())+1 , nb +1 )
mergedUpdated = true
}
if !mergedUpdated {
answer += uint (merged .last ()) - uint (merged .start ) + 1
mergedUsed = false
}
continue
} else {
if !canMerge16 (cura , curb ) {
if cura .start < curb .start {
answer += uint (cura .last ()) - uint (cura .start ) + 1
na ++
} else {
answer += uint (curb .last ()) - uint (curb .start ) + 1
nb ++
}
} else {
merged = mergeInterval16s (cura , curb )
mergedUsed = true
na = rc .indexOfIntervalAtOrAfter (int (merged .last ())+1 , na +1 )
nb = b .indexOfIntervalAtOrAfter (int (merged .last ())+1 , nb +1 )
}
}
}
var aDone , bDone bool
if na >= alim {
aDone = true
}
if nb >= blim {
bDone = true
}
if mergedUsed {
if !aDone {
aAdds :
for na < alim {
cura = rc .iv [na ]
if canMerge16 (cura , merged ) {
merged = mergeInterval16s (cura , merged )
na = rc .indexOfIntervalAtOrAfter (int (merged .last ())+1 , na +1 )
} else {
break aAdds
}
}
}
if !bDone {
bAdds :
for nb < blim {
curb = b .iv [nb ]
if canMerge16 (curb , merged ) {
merged = mergeInterval16s (curb , merged )
nb = b .indexOfIntervalAtOrAfter (int (merged .last ())+1 , nb +1 )
} else {
break bAdds
}
}
}
answer += uint (merged .last ()) - uint (merged .start ) + 1
}
for _ , r := range rc .iv [na :] {
answer += uint (r .last ()) - uint (r .start ) + 1
}
for _ , r := range b .iv [nb :] {
answer += uint (r .last ()) - uint (r .start ) + 1
}
return answer
}
func (rc *runContainer16 ) indexOfIntervalAtOrAfter (key int , startIndex int ) int {
w , already , _ := rc .searchRange (key , startIndex , 0 )
if already {
return w
}
return w + 1
}
func (rc *runContainer16 ) intersect (b *runContainer16 ) *runContainer16 {
a := rc
numa := int (len (a .iv ))
numb := int (len (b .iv ))
res := &runContainer16 {}
if numa == 0 || numb == 0 {
return res
}
if numa == 1 && numb == 1 {
if !haveOverlap16 (a .iv [0 ], b .iv [0 ]) {
return res
}
}
var output []interval16
var acuri int
var bcuri int
astart := int (a .iv [acuri ].start )
bstart := int (b .iv [bcuri ].start )
var intersection interval16
var leftoverstart int
var isOverlap , isLeftoverA , isLeftoverB bool
var done bool
toploop :
for acuri < numa && bcuri < numb {
isOverlap , isLeftoverA , isLeftoverB , leftoverstart , intersection =
intersectWithLeftover16 (astart , int (a .iv [acuri ].last ()), bstart , int (b .iv [bcuri ].last ()))
if !isOverlap {
switch {
case astart < bstart :
acuri , done = a .findNextIntervalThatIntersectsStartingFrom (acuri +1 , bstart )
if done {
break toploop
}
astart = int (a .iv [acuri ].start )
case astart > bstart :
bcuri , done = b .findNextIntervalThatIntersectsStartingFrom (bcuri +1 , astart )
if done {
break toploop
}
bstart = int (b .iv [bcuri ].start )
}
} else {
output = append (output , intersection )
switch {
case isLeftoverA :
astart = leftoverstart
bcuri ++
if bcuri >= numb {
break toploop
}
bstart = int (b .iv [bcuri ].start )
case isLeftoverB :
bstart = leftoverstart
acuri ++
if acuri >= numa {
break toploop
}
astart = int (a .iv [acuri ].start )
default :
acuri ++
if acuri >= numa {
break toploop
}
astart = int (a .iv [acuri ].start )
bcuri ++
if bcuri >= numb {
break toploop
}
bstart = int (b .iv [bcuri ].start )
}
}
}
if len (output ) == 0 {
return res
}
res .iv = output
return res
}
func (rc *runContainer16 ) intersectCardinality (b *runContainer16 ) int {
answer := int (0 )
a := rc
numa := int (len (a .iv ))
numb := int (len (b .iv ))
if numa == 0 || numb == 0 {
return 0
}
if numa == 1 && numb == 1 {
if !haveOverlap16 (a .iv [0 ], b .iv [0 ]) {
return 0
}
}
var acuri int
var bcuri int
astart := int (a .iv [acuri ].start )
bstart := int (b .iv [bcuri ].start )
var intersection interval16
var leftoverstart int
var isOverlap , isLeftoverA , isLeftoverB bool
var done bool
pass := 0
toploop :
for acuri < numa && bcuri < numb {
pass ++
isOverlap , isLeftoverA , isLeftoverB , leftoverstart , intersection =
intersectWithLeftover16 (astart , int (a .iv [acuri ].last ()), bstart , int (b .iv [bcuri ].last ()))
if !isOverlap {
switch {
case astart < bstart :
acuri , done = a .findNextIntervalThatIntersectsStartingFrom (acuri +1 , bstart )
if done {
break toploop
}
astart = int (a .iv [acuri ].start )
case astart > bstart :
bcuri , done = b .findNextIntervalThatIntersectsStartingFrom (bcuri +1 , astart )
if done {
break toploop
}
bstart = int (b .iv [bcuri ].start )
}
} else {
answer += int (intersection .last ()) - int (intersection .start ) + 1
switch {
case isLeftoverA :
astart = leftoverstart
bcuri ++
if bcuri >= numb {
break toploop
}
bstart = int (b .iv [bcuri ].start )
case isLeftoverB :
bstart = leftoverstart
acuri ++
if acuri >= numa {
break toploop
}
astart = int (a .iv [acuri ].start )
default :
acuri ++
if acuri >= numa {
break toploop
}
astart = int (a .iv [acuri ].start )
bcuri ++
if bcuri >= numb {
break toploop
}
bstart = int (b .iv [bcuri ].start )
}
}
}
return answer
}
func (rc *runContainer16 ) contains (key uint16 ) bool {
_ , in , _ := rc .search (int (key ))
return in
}
func (rc *runContainer16 ) numIntervals () int {
return len (rc .iv )
}
func (rc *runContainer16 ) searchRange (key int , startIndex int , endxIndex int ) (whichInterval16 int , alreadyPresent bool , numCompares int ) {
n := int (len (rc .iv ))
if n == 0 {
return -1 , false , 0
}
if endxIndex == 0 {
endxIndex = n
}
i , j := startIndex , endxIndex
for i < j {
h := i + (j -i )/2
numCompares ++
if !(key < int (rc .iv [h ].start )) {
i = h + 1
} else {
j = h
}
}
below := i
whichInterval16 = below - 1
if below == n {
if key < int (rc .iv [n -1 ].last ())+1 {
alreadyPresent = true
return
}
return
}
if below == 0 {
return
}
if key >= int (rc .iv [below -1 ].start ) && key < int (rc .iv [below -1 ].last ())+1 {
alreadyPresent = true
return
}
return
}
func (rc *runContainer16 ) search (key int ) (whichInterval16 int , alreadyPresent bool , numCompares int ) {
return rc .searchRange (key , 0 , 0 )
}
func (rc *runContainer16 ) getCardinality () int {
n := 0
for _ , p := range rc .iv {
n += p .runlen ()
}
return n
}
func (rc *runContainer16 ) isEmpty () bool {
return len (rc .iv ) == 0
}
func (rc *runContainer16 ) AsSlice () []uint16 {
s := make ([]uint16 , rc .getCardinality ())
j := 0
for _ , p := range rc .iv {
for i := p .start ; i <= p .last (); i ++ {
s [j ] = i
j ++
}
}
return s
}
func newRunContainer16() *runContainer16 {
return &runContainer16 {}
}
func newRunContainer16CopyIv(iv []interval16 ) *runContainer16 {
rc := &runContainer16 {
iv : make ([]interval16 , len (iv )),
}
copy (rc .iv , iv )
return rc
}
func (rc *runContainer16 ) Clone () *runContainer16 {
rc2 := newRunContainer16CopyIv (rc .iv )
return rc2
}
func newRunContainer16TakeOwnership(iv []interval16 ) *runContainer16 {
rc := &runContainer16 {
iv : iv ,
}
return rc
}
const baseRc16Size = int (unsafe .Sizeof (runContainer16 {}))
const perIntervalRc16Size = int (unsafe .Sizeof (interval16 {}))
const baseDiskRc16Size = int (unsafe .Sizeof (uint16 (0 )))
func (rc *runContainer16 ) getSizeInBytes () int {
return perIntervalRc16Size *len (rc .iv ) + baseRc16Size
}
func runContainer16SerializedSizeInBytes(numRuns int ) int {
return perIntervalRc16Size *numRuns + baseDiskRc16Size
}
func (rc *runContainer16 ) Add (k uint16 ) (wasNew bool ) {
k64 := int (k )
index , present , _ := rc .search (k64 )
if present {
return
}
wasNew = true
n := int (len (rc .iv ))
if index == -1 {
if n > 0 {
if rc .iv [0 ].start == k +1 {
rc .iv [0 ].start = k
rc .iv [0 ].length ++
return
}
}
rc .iv = append ([]interval16 {newInterval16Range (k , k )}, rc .iv ...)
return
}
if index >= n -1 {
if int (rc .iv [n -1 ].last ())+1 == k64 {
rc .iv [n -1 ].length ++
return
}
rc .iv = append (rc .iv , newInterval16Range (k , k ))
return
}
left := index
right := index + 1
if int (rc .iv [left ].last ())+1 == k64 && int (rc .iv [right ].start ) == k64 +1 {
rc .iv [left ].length = rc .iv [right ].last () - rc .iv [left ].start
rc .iv = append (rc .iv [:left +1 ], rc .iv [right +1 :]...)
return
}
if int (rc .iv [left ].last ())+1 == k64 {
rc .iv [left ].length ++
return
}
if int (rc .iv [right ].start ) == k64 +1 {
rc .iv [right ].start = k
rc .iv [right ].length ++
return
}
tail := append ([]interval16 {newInterval16Range (k , k )}, rc .iv [right :]...)
rc .iv = append (rc .iv [:left +1 ], tail ...)
return
}
type runIterator16 struct {
rc *runContainer16
curIndex int
curPosInIndex uint16
}
func (rc *runContainer16 ) newRunIterator16 () *runIterator16 {
return &runIterator16 {rc : rc , curIndex : 0 , curPosInIndex : 0 }
}
func (rc *runContainer16 ) iterate (cb func (x uint16 ) bool ) bool {
iterator := runIterator16 {rc , 0 , 0 }
for iterator .hasNext () {
if !cb (iterator .next ()) {
return false
}
}
return true
}
func (ri *runIterator16 ) hasNext () bool {
return int (len (ri .rc .iv )) > ri .curIndex +1 ||
(int (len (ri .rc .iv )) == ri .curIndex +1 && ri .rc .iv [ri .curIndex ].length >= ri .curPosInIndex )
}
func (ri *runIterator16 ) next () uint16 {
next := ri .rc .iv [ri .curIndex ].start + ri .curPosInIndex
if ri .curPosInIndex == ri .rc .iv [ri .curIndex ].length {
ri .curPosInIndex = 0
ri .curIndex ++
} else {
ri .curPosInIndex ++
}
return next
}
func (ri *runIterator16 ) peekNext () uint16 {
return ri .rc .iv [ri .curIndex ].start + ri .curPosInIndex
}
func (ri *runIterator16 ) advanceIfNeeded (minval uint16 ) {
if !ri .hasNext () || ri .peekNext () >= minval {
return
}
interval , isPresent , _ := ri .rc .searchRange (int (minval ), ri .curIndex , int (len (ri .rc .iv )))
if isPresent {
ri .curIndex = interval
ri .curPosInIndex = minval - ri .rc .iv [ri .curIndex ].start
} else {
ri .curIndex = interval + 1
ri .curPosInIndex = 0
}
}
type runReverseIterator16 struct {
rc *runContainer16
curIndex int
curPosInIndex uint16
}
func (rc *runContainer16 ) newRunReverseIterator16 () *runReverseIterator16 {
index := int (len (rc .iv )) - 1
pos := uint16 (0 )
if index >= 0 {
pos = rc .iv [index ].length
}
return &runReverseIterator16 {
rc : rc ,
curIndex : index ,
curPosInIndex : pos ,
}
}
func (ri *runReverseIterator16 ) hasNext () bool {
return ri .curIndex > 0 || ri .curIndex == 0 && ri .curPosInIndex >= 0
}
func (ri *runReverseIterator16 ) next () uint16 {
next := ri .rc .iv [ri .curIndex ].start + ri .curPosInIndex
if ri .curPosInIndex > 0 {
ri .curPosInIndex --
} else {
ri .curIndex --
if ri .curIndex >= 0 {
ri .curPosInIndex = ri .rc .iv [ri .curIndex ].length
}
}
return next
}
func (rc *runContainer16 ) newManyRunIterator16 () *runIterator16 {
return rc .newRunIterator16 ()
}
func (ri *runIterator16 ) nextMany (hs uint32 , buf []uint32 ) int {
n := 0
if !ri .hasNext () {
return n
}
for n < len (buf ) {
moreVals := 0
if ri .rc .iv [ri .curIndex ].length >= ri .curPosInIndex {
moreVals = minOfInt (int (ri .rc .iv [ri .curIndex ].length -ri .curPosInIndex )+1 , len (buf )-n )
base := uint32 (ri .rc .iv [ri .curIndex ].start +ri .curPosInIndex ) | hs
buf2 := buf [n : n +moreVals ]
for i := range buf2 {
buf2 [i ] = base + uint32 (i )
}
n += moreVals
}
if moreVals +int (ri .curPosInIndex ) > int (ri .rc .iv [ri .curIndex ].length ) {
ri .curPosInIndex = 0
ri .curIndex ++
if ri .curIndex == int (len (ri .rc .iv )) {
break
}
} else {
ri .curPosInIndex += uint16 (moreVals )
}
}
return n
}
func (ri *runIterator16 ) nextMany64 (hs uint64 , buf []uint64 ) int {
n := 0
if !ri .hasNext () {
return n
}
for n < len (buf ) {
moreVals := 0
if ri .rc .iv [ri .curIndex ].length >= ri .curPosInIndex {
moreVals = minOfInt (int (ri .rc .iv [ri .curIndex ].length -ri .curPosInIndex )+1 , len (buf )-n )
base := uint64 (ri .rc .iv [ri .curIndex ].start +ri .curPosInIndex ) | hs
buf2 := buf [n : n +moreVals ]
for i := range buf2 {
buf2 [i ] = base + uint64 (i )
}
n += moreVals
}
if moreVals +int (ri .curPosInIndex ) > int (ri .rc .iv [ri .curIndex ].length ) {
ri .curPosInIndex = 0
ri .curIndex ++
if ri .curIndex == int (len (ri .rc .iv )) {
break
}
} else {
ri .curPosInIndex += uint16 (moreVals )
}
}
return n
}
func (rc *runContainer16 ) removeKey (key uint16 ) (wasPresent bool ) {
var index int
index , wasPresent , _ = rc .search (int (key ))
if !wasPresent {
return
}
pos := key - rc .iv [index ].start
rc .deleteAt (&index , &pos )
return
}
func (rc *runContainer16 ) deleteAt (curIndex *int , curPosInIndex *uint16 ) {
ci := *curIndex
pos := *curPosInIndex
switch {
case pos == 0 :
if int (rc .iv [ci ].length ) == 0 {
rc .iv = append (rc .iv [:ci ], rc .iv [ci +1 :]...)
*curPosInIndex = 0
} else {
rc .iv [ci ].start ++
rc .iv [ci ].length --
}
case pos == rc .iv [ci ].length :
rc .iv [ci ].length --
*curPosInIndex --
default :
new0 := newInterval16Range (rc .iv [ci ].start , rc .iv [ci ].start +*curPosInIndex -1 )
new1start := int (rc .iv [ci ].start +*curPosInIndex ) + 1
if new1start > int (MaxUint16 ) {
panic ("overflow?!?!" )
}
new1 := newInterval16Range (uint16 (new1start ), rc .iv [ci ].last ())
tail := append ([]interval16 {new0 , new1 }, rc .iv [ci +1 :]...)
rc .iv = append (rc .iv [:ci ], tail ...)
*curIndex ++
*curPosInIndex = 0
}
}
func have4Overlap16(astart , alast , bstart , blast int ) bool {
if alast +1 <= bstart {
return false
}
return blast +1 > astart
}
func intersectWithLeftover16(astart , alast , bstart , blast int ) (isOverlap , isLeftoverA , isLeftoverB bool , leftoverstart int , intersection interval16 ) {
if !have4Overlap16 (astart , alast , bstart , blast ) {
return
}
isOverlap = true
if bstart > astart {
intersection .start = uint16 (bstart )
} else {
intersection .start = uint16 (astart )
}
switch {
case blast < alast :
isLeftoverA = true
leftoverstart = blast + 1
intersection .length = uint16 (blast ) - intersection .start
case alast < blast :
isLeftoverB = true
leftoverstart = alast + 1
intersection .length = uint16 (alast ) - intersection .start
default :
intersection .length = uint16 (alast ) - intersection .start
}
return
}
func (rc *runContainer16 ) findNextIntervalThatIntersectsStartingFrom (startIndex int , key int ) (index int , done bool ) {
w , _ , _ := rc .searchRange (key , startIndex , 0 )
if w < startIndex {
if startIndex == int (len (rc .iv )) {
return startIndex , true
}
return startIndex , false
}
return w , false
}
func sliceToString16(m []interval16 ) string {
s := ""
for i := range m {
s += fmt .Sprintf ("%v: %s, " , i , m [i ])
}
return s
}
func (rc *runContainer16 ) invertlastInterval (origin uint16 , lastIdx int ) []interval16 {
cur := rc .iv [lastIdx ]
if cur .last () == MaxUint16 {
if cur .start == origin {
return nil
}
return []interval16 {newInterval16Range (origin , cur .start -1 )}
}
if cur .start == origin {
return []interval16 {newInterval16Range (cur .last ()+1 , MaxUint16 )}
}
return []interval16 {
newInterval16Range (origin , cur .start -1 ),
newInterval16Range (cur .last ()+1 , MaxUint16 ),
}
}
func (rc *runContainer16 ) invert () *runContainer16 {
ni := len (rc .iv )
var m []interval16
switch ni {
case 0 :
return &runContainer16 {iv : []interval16 {newInterval16Range (0 , MaxUint16 )}}
case 1 :
return &runContainer16 {iv : rc .invertlastInterval (0 , 0 )}
}
var invstart int
ult := ni - 1
for i , cur := range rc .iv {
if i == ult {
m = append (m , rc .invertlastInterval (uint16 (invstart ), i )...)
break
}
if cur .start > 0 {
m = append (m , newInterval16Range (uint16 (invstart ), cur .start -1 ))
}
invstart = int (cur .last () + 1 )
}
return &runContainer16 {iv : m }
}
func (iv interval16 ) equal (b interval16 ) bool {
return iv .start == b .start && iv .length == b .length
}
func (iv interval16 ) isSuperSetOf (b interval16 ) bool {
return iv .start <= b .start && b .last () <= iv .last ()
}
func (iv interval16 ) subtractInterval (del interval16 ) (left []interval16 , delcount int ) {
isect , isEmpty := intersectInterval16s (iv , del )
if isEmpty {
return nil , 0
}
if del .isSuperSetOf (iv ) {
return nil , iv .runlen ()
}
switch {
case isect .start > iv .start && isect .last () < iv .last ():
new0 := newInterval16Range (iv .start , isect .start -1 )
new1 := newInterval16Range (isect .last ()+1 , iv .last ())
return []interval16 {new0 , new1 }, isect .runlen ()
case isect .start == iv .start :
return []interval16 {newInterval16Range (isect .last ()+1 , iv .last ())}, isect .runlen ()
default :
return []interval16 {newInterval16Range (iv .start , isect .start -1 )}, isect .runlen ()
}
}
func (rc *runContainer16 ) isubtract (del interval16 ) {
origiv := make ([]interval16 , len (rc .iv ))
copy (origiv , rc .iv )
n := int (len (rc .iv ))
if n == 0 {
return
}
_ , isEmpty := intersectInterval16s (newInterval16Range (rc .iv [0 ].start , rc .iv [n -1 ].last ()), del )
if isEmpty {
return
}
istart , startAlready , _ := rc .search (int (del .start ))
ilast , lastAlready , _ := rc .search (int (del .last ()))
if istart == -1 {
if ilast == n -1 && !lastAlready {
rc .iv = nil
return
}
}
switch {
case startAlready && lastAlready :
res0 , _ := rc .iv [istart ].subtractInterval (del )
lost := 1 + ilast - istart
changeSize := int (len (res0 )) - lost
newSize := int (len (rc .iv )) + changeSize
if ilast != istart {
res1 , _ := rc .iv [ilast ].subtractInterval (del )
res0 = append (res0 , res1 ...)
changeSize = int (len (res0 )) - lost
newSize = int (len (rc .iv )) + changeSize
}
switch {
case changeSize < 0 :
copy (rc .iv [istart +int (len (res0 )):], rc .iv [ilast +1 :])
copy (rc .iv [istart :istart +int (len (res0 ))], res0 )
rc .iv = rc .iv [:newSize ]
return
case changeSize == 0 :
copy (rc .iv [istart :istart +int (len (res0 ))], res0 )
return
default :
rc .iv = append (rc .iv , interval16 {})
copy (rc .iv [ilast +2 :], rc .iv [ilast +1 :])
copy (rc .iv [istart :istart +2 ], res0 )
return
}
case !startAlready && !lastAlready :
pre := rc .iv [:istart +1 ]
if ilast == n -1 {
rc .iv = pre
return
}
lost := ilast - istart
changeSize := -lost
newSize := int (len (rc .iv )) + changeSize
if changeSize != 0 {
copy (rc .iv [ilast +1 +changeSize :], rc .iv [ilast +1 :])
}
rc .iv = rc .iv [:newSize ]
return
case startAlready && !lastAlready :
res0 , _ := rc .iv [istart ].subtractInterval (del )
if len (res0 ) > 0 {
rc .iv [istart ] = res0 [0 ]
}
lost := 1 + (ilast - istart )
changeSize := int (len (res0 )) - lost
newSize := int (len (rc .iv )) + changeSize
if changeSize != 0 {
copy (rc .iv [ilast +1 +changeSize :], rc .iv [ilast +1 :])
}
rc .iv = rc .iv [:newSize ]
return
case !startAlready && lastAlready :
res1 , _ := rc .iv [ilast ].subtractInterval (del )
lost := ilast - istart
changeSize := int (len (res1 )) - lost
newSize := int (len (rc .iv )) + changeSize
if changeSize != 0 {
copy (rc .iv [ilast +1 +changeSize :], rc .iv [ilast +1 :])
}
copy (rc .iv [istart +1 :], res1 )
rc .iv = rc .iv [:newSize ]
return
}
}
func (rc *runContainer16 ) AndNotRunContainer16 (b *runContainer16 ) *runContainer16 {
if len (b .iv ) == 0 || len (rc .iv ) == 0 {
return rc
}
dst := newRunContainer16 ()
apos := 0
bpos := 0
a := rc
astart := a .iv [apos ].start
alast := a .iv [apos ].last ()
bstart := b .iv [bpos ].start
blast := b .iv [bpos ].last ()
alen := len (a .iv )
blen := len (b .iv )
for apos < alen && bpos < blen {
switch {
case alast < bstart :
dst .iv = append (dst .iv , newInterval16Range (astart , alast ))
apos ++
if apos < alen {
astart = a .iv [apos ].start
alast = a .iv [apos ].last ()
}
case blast < astart :
bpos ++
if bpos < blen {
bstart = b .iv [bpos ].start
blast = b .iv [bpos ].last ()
}
default :
if astart < bstart {
dst .iv = append (dst .iv , newInterval16Range (astart , bstart -1 ))
}
if alast > blast {
astart = blast + 1
} else {
apos ++
if apos < alen {
astart = a .iv [apos ].start
alast = a .iv [apos ].last ()
}
}
}
}
if apos < alen {
dst .iv = append (dst .iv , newInterval16Range (astart , alast ))
apos ++
if apos < alen {
dst .iv = append (dst .iv , a .iv [apos :]...)
}
}
return dst
}
func (rc *runContainer16 ) numberOfRuns () (nr int ) {
return len (rc .iv )
}
func (rc *runContainer16 ) containerType () contype {
return run16Contype
}
func (rc *runContainer16 ) equals16 (srb *runContainer16 ) bool {
if rc == srb {
return true
}
if len (srb .iv ) != len (rc .iv ) {
return false
}
for i , v := range rc .iv {
if v != srb .iv [i ] {
return false
}
}
return true
}
var _ container = &runContainer16 {}
func (rc *runContainer16 ) clone () container {
return newRunContainer16CopyIv (rc .iv )
}
func (rc *runContainer16 ) minimum () uint16 {
return rc .iv [0 ].start
}
func (rc *runContainer16 ) maximum () uint16 {
return rc .iv [len (rc .iv )-1 ].last ()
}
func (rc *runContainer16 ) isFull () bool {
return (len (rc .iv ) == 1 ) && ((rc .iv [0 ].start == 0 ) && (rc .iv [0 ].last () == MaxUint16 ))
}
func (rc *runContainer16 ) and (a container ) container {
if rc .isFull () {
return a .clone ()
}
switch c := a .(type ) {
case *runContainer16 :
return rc .intersect (c )
case *arrayContainer :
return rc .andArray (c )
case *bitmapContainer :
return rc .andBitmapContainer (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) andCardinality (a container ) int {
switch c := a .(type ) {
case *runContainer16 :
return int (rc .intersectCardinality (c ))
case *arrayContainer :
return rc .andArrayCardinality (c )
case *bitmapContainer :
return rc .andBitmapContainerCardinality (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) andBitmapContainer (bc *bitmapContainer ) container {
bc2 := newBitmapContainerFromRun (rc )
return bc2 .andBitmap (bc )
}
func (rc *runContainer16 ) andArrayCardinality (ac *arrayContainer ) int {
pos := 0
answer := 0
maxpos := ac .getCardinality ()
if maxpos == 0 {
return 0
}
v := ac .content [pos ]
mainloop :
for _ , p := range rc .iv {
for v < p .start {
pos ++
if pos == maxpos {
break mainloop
}
v = ac .content [pos ]
}
for v <= p .last () {
answer ++
pos ++
if pos == maxpos {
break mainloop
}
v = ac .content [pos ]
}
}
return answer
}
func (rc *runContainer16 ) iand (a container ) container {
if rc .isFull () {
return a .clone ()
}
switch c := a .(type ) {
case *runContainer16 :
return rc .inplaceIntersect (c )
case *arrayContainer :
return rc .andArray (c )
case *bitmapContainer :
return rc .iandBitmapContainer (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) inplaceIntersect (rc2 *runContainer16 ) container {
sect := rc .intersect (rc2 )
*rc = *sect
return rc
}
func (rc *runContainer16 ) iandBitmapContainer (bc *bitmapContainer ) container {
isect := rc .andBitmapContainer (bc )
*rc = *newRunContainer16FromContainer (isect )
return rc
}
func (rc *runContainer16 ) andArray (ac *arrayContainer ) container {
if len (rc .iv ) == 0 {
return newArrayContainer ()
}
acCardinality := ac .getCardinality ()
c := newArrayContainerCapacity (acCardinality )
for rlePos , arrayPos := 0 , 0 ; arrayPos < acCardinality ; {
iv := rc .iv [rlePos ]
arrayVal := ac .content [arrayPos ]
for iv .last () < arrayVal {
rlePos ++
if rlePos == len (rc .iv ) {
return c
}
iv = rc .iv [rlePos ]
}
if iv .start > arrayVal {
arrayPos = advanceUntil (ac .content , arrayPos , len (ac .content ), iv .start )
} else {
c .content = append (c .content , arrayVal )
arrayPos ++
}
}
return c
}
func (rc *runContainer16 ) andNot (a container ) container {
switch c := a .(type ) {
case *arrayContainer :
return rc .andNotArray (c )
case *bitmapContainer :
return rc .andNotBitmap (c )
case *runContainer16 :
return rc .andNotRunContainer16 (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) fillLeastSignificant16bits (x []uint32 , i int , mask uint32 ) int {
k := i
var val int
for _ , p := range rc .iv {
n := p .runlen ()
for j := int (0 ); j < n ; j ++ {
val = int (p .start ) + j
x [k ] = uint32 (val ) | mask
k ++
}
}
return k
}
func (rc *runContainer16 ) getShortIterator () shortPeekable {
return rc .newRunIterator16 ()
}
func (rc *runContainer16 ) getReverseIterator () shortIterable {
return rc .newRunReverseIterator16 ()
}
func (rc *runContainer16 ) getManyIterator () manyIterable {
return rc .newManyRunIterator16 ()
}
func (rc *runContainer16 ) iaddRange (firstOfRange , endx int ) container {
if firstOfRange > endx {
panic (fmt .Sprintf ("invalid %v = endx > firstOfRange" , endx ))
}
if firstOfRange == endx {
return rc
}
addme := newRunContainer16TakeOwnership ([]interval16 {
{
start : uint16 (firstOfRange ),
length : uint16 (endx - 1 - firstOfRange ),
},
})
*rc = *rc .union (addme )
return rc
}
func (rc *runContainer16 ) iremoveRange (firstOfRange , endx int ) container {
if firstOfRange > endx {
panic (fmt .Sprintf ("request to iremove empty set [%v, %v)," +
" nothing to do." , firstOfRange , endx ))
}
if firstOfRange == endx {
return rc
}
x := newInterval16Range (uint16 (firstOfRange ), uint16 (endx -1 ))
rc .isubtract (x )
return rc
}
func (rc *runContainer16 ) not (firstOfRange , endx int ) container {
if firstOfRange > endx {
panic (fmt .Sprintf ("invalid %v = endx > firstOfRange = %v" , endx , firstOfRange ))
}
return rc .Not (firstOfRange , endx )
}
func (rc *runContainer16 ) Not (firstOfRange , endx int ) *runContainer16 {
if firstOfRange > endx {
panic (fmt .Sprintf ("invalid %v = endx > firstOfRange == %v" , endx , firstOfRange ))
}
if firstOfRange >= endx {
return rc .Clone ()
}
a := rc
nota := a .invert ()
bs := []interval16 {newInterval16Range (uint16 (firstOfRange ), uint16 (endx -1 ))}
b := newRunContainer16TakeOwnership (bs )
notAintersectB := nota .intersect (b )
aMinusB := a .AndNotRunContainer16 (b )
rc2 := notAintersectB .union (aMinusB )
return rc2
}
func (rc *runContainer16 ) equals (o container ) bool {
srb , ok := o .(*runContainer16 )
if !ok {
val , valok := o .(*runContainer16 )
if valok {
srb = val
ok = true
}
}
if ok {
if rc == srb {
return true
}
if len (srb .iv ) != len (rc .iv ) {
return false
}
for i , v := range rc .iv {
if v != srb .iv [i ] {
return false
}
}
return true
}
if o .getCardinality () != rc .getCardinality () {
return false
}
rit := rc .getShortIterator ()
bit := o .getShortIterator ()
for rit .hasNext () {
if bit .next () != rit .next () {
return false
}
}
return true
}
func (rc *runContainer16 ) iaddReturnMinimized (x uint16 ) container {
rc .Add (x )
return rc
}
func (rc *runContainer16 ) iadd (x uint16 ) (wasNew bool ) {
return rc .Add (x )
}
func (rc *runContainer16 ) iremoveReturnMinimized (x uint16 ) container {
rc .removeKey (x )
return rc
}
func (rc *runContainer16 ) iremove (x uint16 ) bool {
return rc .removeKey (x )
}
func (rc *runContainer16 ) or (a container ) container {
if rc .isFull () {
return rc .clone ()
}
switch c := a .(type ) {
case *runContainer16 :
return rc .union (c )
case *arrayContainer :
return rc .orArray (c )
case *bitmapContainer :
return rc .orBitmapContainer (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) orCardinality (a container ) int {
switch c := a .(type ) {
case *runContainer16 :
return int (rc .unionCardinality (c ))
case *arrayContainer :
return rc .orArrayCardinality (c )
case *bitmapContainer :
return rc .orBitmapContainerCardinality (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) orBitmapContainer (bc *bitmapContainer ) container {
bc2 := newBitmapContainerFromRun (rc )
return bc2 .iorBitmap (bc )
}
func (rc *runContainer16 ) andBitmapContainerCardinality (bc *bitmapContainer ) int {
answer := 0
for i := range rc .iv {
answer += bc .getCardinalityInRange (uint (rc .iv [i ].start ), uint (rc .iv [i ].last ())+1 )
}
return answer
}
func (rc *runContainer16 ) orBitmapContainerCardinality (bc *bitmapContainer ) int {
return rc .getCardinality () + bc .getCardinality () - rc .andBitmapContainerCardinality (bc )
}
func (rc *runContainer16 ) orArray (ac *arrayContainer ) container {
if ac .isEmpty () {
return rc .clone ()
}
if rc .isEmpty () {
return ac .clone ()
}
intervals , cardMinusOne := runArrayUnionToRuns (rc , ac )
result := newRunContainer16TakeOwnership (intervals )
if len (intervals ) >= 2048 && cardMinusOne >= arrayDefaultMaxSize {
return newBitmapContainerFromRun (result )
}
if len (intervals )*2 > 1 +int (cardMinusOne ) {
return result .toArrayContainer ()
}
return result
}
func (rc *runContainer16 ) orArrayCardinality (ac *arrayContainer ) int {
return ac .getCardinality () + rc .getCardinality () - rc .andArrayCardinality (ac )
}
func (rc *runContainer16 ) ior (a container ) container {
if rc .isFull () {
return rc
}
switch c := a .(type ) {
case *runContainer16 :
return rc .inplaceUnion (c )
case *arrayContainer :
return rc .iorArray (c )
case *bitmapContainer :
return rc .iorBitmapContainer (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) inplaceUnion (rc2 *runContainer16 ) container {
for _ , p := range rc2 .iv {
last := int (p .last ())
for i := int (p .start ); i <= last ; i ++ {
rc .Add (uint16 (i ))
}
}
return rc
}
func (rc *runContainer16 ) iorBitmapContainer (bc *bitmapContainer ) container {
it := bc .getShortIterator ()
for it .hasNext () {
rc .Add (it .next ())
}
return rc
}
func (rc *runContainer16 ) iorArray (ac *arrayContainer ) container {
if rc .isEmpty () {
return ac .clone ()
}
if ac .isEmpty () {
return rc
}
var cardMinusOne uint16
rc .iv , cardMinusOne = runArrayUnionToRuns (rc , ac )
if len (rc .iv ) >= 2048 && cardMinusOne >= arrayDefaultMaxSize {
return newBitmapContainerFromRun (rc )
}
if len (rc .iv )*2 > 1 +int (cardMinusOne ) {
return rc .toArrayContainer ()
}
return rc
}
func runArrayUnionToRuns(rc *runContainer16 , ac *arrayContainer ) ([]interval16 , uint16 ) {
pos1 := 0
pos2 := 0
length1 := len (ac .content )
length2 := len (rc .iv )
target := make ([]interval16 , 0 , len (rc .iv ))
var previousInterval interval16
var cardMinusOne uint16
if ac .content [0 ] < rc .iv [0 ].start {
previousInterval .start = ac .content [0 ]
previousInterval .length = 0
pos1 ++
} else {
previousInterval .start = rc .iv [0 ].start
previousInterval .length = rc .iv [0 ].length
pos2 ++
}
for pos1 < length1 || pos2 < length2 {
if pos1 < length1 {
s1 := ac .content [pos1 ]
if s1 <= previousInterval .start +previousInterval .length {
pos1 ++
continue
}
if previousInterval .last () < MaxUint16 && previousInterval .last ()+1 == s1 {
previousInterval .length ++
pos1 ++
continue
}
}
if pos2 < length2 {
range2 := rc .iv [pos2 ]
if range2 .start <= previousInterval .last () || range2 .start > 0 && range2 .start -1 == previousInterval .last () {
pos2 ++
if previousInterval .last () < range2 .last () {
previousInterval .length = range2 .last () - previousInterval .start
}
continue
}
}
cardMinusOne += previousInterval .length + 1
target = append (target , previousInterval )
if pos2 == length2 || pos1 < length1 && ac .content [pos1 ] < rc .iv [pos2 ].start {
previousInterval .start = ac .content [pos1 ]
previousInterval .length = 0
pos1 ++
} else {
previousInterval = rc .iv [pos2 ]
pos2 ++
}
}
cardMinusOne += previousInterval .length
target = append (target , previousInterval )
return target , cardMinusOne
}
func (rc *runContainer16 ) lazyIOR (a container ) container {
return rc .ior (a )
}
func (rc *runContainer16 ) lazyOR (a container ) container {
return rc .or (a )
}
func (rc *runContainer16 ) intersects (a container ) bool {
isect := rc .and (a )
return !isect .isEmpty ()
}
func (rc *runContainer16 ) xor (a container ) container {
switch c := a .(type ) {
case *arrayContainer :
return rc .xorArray (c )
case *bitmapContainer :
return rc .xorBitmap (c )
case *runContainer16 :
return rc .xorRunContainer16 (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) iandNot (a container ) container {
switch c := a .(type ) {
case *arrayContainer :
return rc .iandNotArray (c )
case *bitmapContainer :
return rc .iandNotBitmap (c )
case *runContainer16 :
return rc .iandNotRunContainer16 (c )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) inot (firstOfRange , endx int ) container {
if firstOfRange > endx {
panic (fmt .Sprintf ("invalid %v = endx > firstOfRange = %v" , endx , firstOfRange ))
}
if firstOfRange > endx {
return rc
}
rc = rc .Not (firstOfRange , endx )
return rc
}
func (rc *runContainer16 ) rank (x uint16 ) int {
n := int (len (rc .iv ))
xx := int (x )
w , already , _ := rc .search (xx )
if w < 0 {
return 0
}
if !already && w == n -1 {
return rc .getCardinality ()
}
var rnk int
if !already {
for i := int (0 ); i <= w ; i ++ {
rnk += rc .iv [i ].runlen ()
}
return int (rnk )
}
for i := int (0 ); i < w ; i ++ {
rnk += rc .iv [i ].runlen ()
}
rnk += int (x -rc .iv [w ].start ) + 1
return int (rnk )
}
func (rc *runContainer16 ) selectInt (x uint16 ) int {
var offset int
for k := range rc .iv {
nextOffset := offset + rc .iv [k ].runlen ()
if nextOffset > int (x ) {
return int (int (rc .iv [k ].start ) + (int (x ) - offset ))
}
offset = nextOffset
}
panic ("cannot select x" )
}
func (rc *runContainer16 ) andNotRunContainer16 (b *runContainer16 ) container {
return rc .AndNotRunContainer16 (b )
}
func (rc *runContainer16 ) andNotArray (ac *arrayContainer ) container {
rcb := rc .toBitmapContainer ()
acb := ac .toBitmapContainer ()
return rcb .andNotBitmap (acb )
}
func (rc *runContainer16 ) andNotBitmap (bc *bitmapContainer ) container {
rcb := rc .toBitmapContainer ()
return rcb .andNotBitmap (bc )
}
func (rc *runContainer16 ) toBitmapContainer () *bitmapContainer {
bc := newBitmapContainer ()
for i := range rc .iv {
bc .iaddRange (int (rc .iv [i ].start ), int (rc .iv [i ].last ())+1 )
}
bc .computeCardinality ()
return bc
}
func (rc *runContainer16 ) iandNotRunContainer16 (x2 *runContainer16 ) container {
rcb := rc .toBitmapContainer ()
x2b := x2 .toBitmapContainer ()
rcb .iandNotBitmapSurely (x2b )
rc2 := newRunContainer16FromBitmapContainer (rcb )
*rc = *rc2
return rc
}
func (rc *runContainer16 ) iandNotArray (ac *arrayContainer ) container {
rcb := rc .toBitmapContainer ()
acb := ac .toBitmapContainer ()
rcb .iandNotBitmapSurely (acb )
rc2 := newRunContainer16FromBitmapContainer (rcb )
*rc = *rc2
return rc
}
func (rc *runContainer16 ) iandNotBitmap (bc *bitmapContainer ) container {
rcb := rc .toBitmapContainer ()
rcb .iandNotBitmapSurely (bc )
rc2 := newRunContainer16FromBitmapContainer (rcb )
*rc = *rc2
return rc
}
func (rc *runContainer16 ) xorRunContainer16 (x2 *runContainer16 ) container {
rcb := rc .toBitmapContainer ()
x2b := x2 .toBitmapContainer ()
return rcb .xorBitmap (x2b )
}
func (rc *runContainer16 ) xorArray (ac *arrayContainer ) container {
rcb := rc .toBitmapContainer ()
acb := ac .toBitmapContainer ()
return rcb .xorBitmap (acb )
}
func (rc *runContainer16 ) xorBitmap (bc *bitmapContainer ) container {
rcb := rc .toBitmapContainer ()
return rcb .xorBitmap (bc )
}
func (rc *runContainer16 ) toEfficientContainer () container {
sizeAsRunContainer := rc .getSizeInBytes ()
sizeAsBitmapContainer := bitmapContainerSizeInBytes ()
card := rc .getCardinality ()
sizeAsArrayContainer := arrayContainerSizeInBytes (card )
if sizeAsRunContainer <= minOfInt (sizeAsBitmapContainer , sizeAsArrayContainer ) {
return rc
}
if card <= arrayDefaultMaxSize {
return rc .toArrayContainer ()
}
bc := newBitmapContainerFromRun (rc )
return bc
}
func (rc *runContainer16 ) toArrayContainer () *arrayContainer {
ac := newArrayContainer ()
for i := range rc .iv {
ac .iaddRange (int (rc .iv [i ].start ), int (rc .iv [i ].last ())+1 )
}
return ac
}
func newRunContainer16FromContainer(c container ) *runContainer16 {
switch x := c .(type ) {
case *runContainer16 :
return x .Clone ()
case *arrayContainer :
return newRunContainer16FromArray (x )
case *bitmapContainer :
return newRunContainer16FromBitmapContainer (x )
}
panic ("unsupported container type" )
}
func (rc *runContainer16 ) And (b *Bitmap ) *Bitmap {
out := NewBitmap ()
for _ , p := range rc .iv {
plast := p .last ()
for i := p .start ; i <= plast ; i ++ {
if b .Contains (uint32 (i )) {
out .Add (uint32 (i ))
}
}
}
return out
}
func (rc *runContainer16 ) Xor (b *Bitmap ) *Bitmap {
out := b .Clone ()
for _ , p := range rc .iv {
plast := p .last ()
for v := p .start ; v <= plast ; v ++ {
w := uint32 (v )
if out .Contains (w ) {
out .RemoveRange (uint64 (w ), uint64 (w +1 ))
} else {
out .Add (w )
}
}
}
return out
}
func (rc *runContainer16 ) Or (b *Bitmap ) *Bitmap {
out := b .Clone ()
for _ , p := range rc .iv {
plast := p .last ()
for v := p .start ; v <= plast ; v ++ {
out .Add (uint32 (v ))
}
}
return out
}
func (rc *runContainer16 ) serializedSizeInBytes () int {
return 2 + len (rc .iv )*4
}
func (rc *runContainer16 ) addOffset (x uint16 ) (container , container ) {
var low , high *runContainer16
if len (rc .iv ) == 0 {
return nil , nil
}
first := uint32 (rc .iv [0 ].start ) + uint32 (x )
if highbits (first ) == 0 {
low = newRunContainer16 ()
}
last := uint32 (rc .iv [len (rc .iv )-1 ].start )
last += uint32 (rc .iv [len (rc .iv )-1 ].length )
last += uint32 (x )
if highbits (last ) > 0 {
high = newRunContainer16 ()
}
for _ , iv := range rc .iv {
val := int (iv .start ) + int (x )
finalVal := int (val ) + int (iv .length )
if val <= 0xffff {
if finalVal <= 0xffff {
low .iv = append (low .iv , interval16 {uint16 (val ), iv .length })
} else {
low .iv = append (low .iv , interval16 {uint16 (val ), uint16 (0xffff - val )})
high .iv = append (high .iv , interval16 {uint16 (0 ), uint16 (finalVal & 0xffff )})
}
} else {
high .iv = append (high .iv , interval16 {uint16 (val & 0xffff ), iv .length })
}
}
if low == nil {
return nil , high
}
if high == nil {
return low , nil
}
return low , high
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .